<?php
/**
 * Edge TTS HTTP 服务
 * 提供文本转语音功能和语音列表查询
 */
require __DIR__ . '/vendor/autoload.php';

use Afaya\EdgeTTS\Service\EdgeTTS;

class TTSService {
    private EdgeTTS $tts;
    private string $htmlPath;
    private array $cache = [];
    private const CACHE_DURATION = 7 * 24 * 60 * 60; // 秒

    public function __construct() {
        $this->tts = new EdgeTTS();
        $this->htmlPath = __DIR__ . '/tts.html';
    }

    /**
     * 处理请求
     */
    public function handleRequest() {
        $action = $_GET['ac'] ?? '';

        try {
            switch ($action) {
                case 'voices':
                    $this->serveVoices();
                    break;
                default:
                    $this->serveAudio();
                    break;
            }
        } catch (InvalidArgumentException $e) {
            $this->serveHtml();
            // $this->sendError(400, 'Invalid parameter: ' . $e->getMessage());
        } catch (Exception $e) {
            $this->sendError(500, 'Server error: ' . $e->getMessage());
        }
    }

    /**
     * 提供 HTML 页面
     */
    private function serveHtml() {
        if (!file_exists($this->htmlPath)) {
            throw new Exception('HTML file not found');
        }
        echo file_get_contents($this->htmlPath);
        exit();
    }

    /**
     * 提供语音列表
     */
    private function serveVoices() {
        $cacheKey = 'voices_list';
        $currentTime = time();

        $this->loadCache();

        // 检查缓存是否有效
        if (isset($this->cache[$cacheKey]) && 
            $this->cache[$cacheKey]['expires'] > $currentTime) {
            $voicesData = $this->cache[$cacheKey]['data'];
        } else {
            // 获取并缓存新数据
            $voices = $this->tts->getVoices();
            $voicesData = $this->groupByField($voices, 'Locale');

            $this->cache[$cacheKey] = [
                'data' => $voicesData,
                'expires' => $currentTime + self::CACHE_DURATION
            ];
            $this->saveCache();
        }

        header('Access-Control-Allow-Origin: *');
        header('cache-control: public, max-age=' . self::CACHE_DURATION);
        header('content-type: application/json');
        echo json_encode($voicesData);
        exit();
    }

    /**
     * 提供音频输出
     */
    private function serveAudio() {
        // 验证输入
        $text = $_GET['text'] ?? $_GET['t'] ?? '';
        if (empty($text)) {
            throw new InvalidArgumentException('Text is required');
        }

        // 过滤输入防止注入
        $text = $this->sanitizeInput($text);
        $voice = $this->sanitizeInput($_GET['voice'] ?? $_GET['v'] ?? 'zh-CN-XiaoyiNeural');

        // 验证并设置参数
        $rate = $this->validateParam($_GET['rate'] ?? '0', 'percentage');
        $volume = $this->validateParam($_GET['volume'] ?? '0', 'percentage');
        $pitch = $this->validateParam($_GET['pitch'] ?? '0', 'pitch');

        // 合成音频
        $this->tts->synthesize(
            $text,
            $voice,
            [
                'rate' => $rate . '%',
                'volume' => $volume . '%',
                'pitch' => $pitch . 'Hz'
            ]
        );

        // 输出音频
        header('content-type: audio/mp3');
        header('cache-control: public, max-age=' . self::CACHE_DURATION);
        echo $this->tts->toRaw();
        exit();
    }

    /**
     * 按字段分组数据
     */
    private function groupByField(array $data, string $keyField): array {
        $res = [];
        foreach ($data as $row) {
            $key = $row[$keyField] ?? null;
            $res[$key][] = $row;
        }
        return $res;
    }

    /**
     * 验证参数
     * @param mixed $value 要验证的值
     * @param string $paramType 参数类型 ('percentage', 'pitch', 等)
     * @param array $options 额外选项，如范围限制 [min, max]
     * @return int 验证后的值
     * @throws InvalidArgumentException 当参数无效时抛出
     */
    private function validateParam($value, string $paramType, array $options = []): int {
        $intValue = (int)$value;
        $min = $options['min'] ?? -100;
        $max = $options['max'] ?? 100;
        $paramName = ucfirst($paramType);
        
        if ($intValue < $min || $intValue > $max) {
            throw new InvalidArgumentException("$paramName must be between $min and $max");
        }
        
        return $intValue;
    }

    /**
     * 清理输入
     */
    private function sanitizeInput($input): string {
        return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
    }

    /**
     * 发送错误响应
     */
    private function sendError(int $statusCode, string $message) {
        http_response_code($statusCode);
        header('content-type: application/json');
        echo json_encode(['error' => $message]);
        exit();
    }

    /**
     * 加载缓存
     */
    private function loadCache() {
        $cacheFile = __DIR__ . '/cache/tts_cache.json';
        if (file_exists($cacheFile)) {
            $cacheData = file_get_contents($cacheFile);
            $this->cache = json_decode($cacheData, true) ?? [];
        }
    }

    /**
     * 保存缓存
     */
    private function saveCache() {
        $cacheDir = __DIR__ . '/cache';
        if (!is_dir($cacheDir)) {
            mkdir($cacheDir, 0755, true);
        }
        $cacheFile = $cacheDir . '/tts_cache.json';
        file_put_contents($cacheFile, json_encode($this->cache));
    }
}

// 初始化并处理请求
$ttsService = new TTSService();
$ttsService->handleRequest();